Skip to content

feat: Chromecast + AirPlay 2 casting#2697

Open
domenkozar wants to merge 4 commits into
AvengeMedia:masterfrom
domenkozar:feat/chromecast-casting
Open

feat: Chromecast + AirPlay 2 casting#2697
domenkozar wants to merge 4 commits into
AvengeMedia:masterfrom
domenkozar:feat/chromecast-casting

Conversation

@domenkozar

@domenkozar domenkozar commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a casting feature that discovers and casts to both Chromecast (_googlecast._tcp) and AirPlay 2 (_airplay._tcp) devices from a single Control Center widget.

  • Chromecast: media casting + screen mirroring (HLS), handled in-process by the dms core via the Go Cast protocol.
  • AirPlay 2: screen mirroring via doubletake (a separate GPLv3 process, never linked into the MIT dms).
  • Screen capture/encode is done by a new dms-cast-helper binary using the GStreamer library (go-gst) — not the gst-launch/ffmpeg/wf-recorder CLIs. The capture pipeline imports the portal's DMA-BUF via VA-API and forces 4:2:0 (I420) chroma (4:4:4 is rejected by most TV decoders → black screen).
  • mDNS discovery prefers avahi (D-Bus API) when present and falls back to a built-in re-browsing browser otherwise.

The main dms binary stays CGO-free; the cast helper is opt-in and needs CGO + GStreamer dev packages. See docs/casting.md for build, firewall, and environment details.

Dependency

AirPlay mirroring relies on the doubletake fork, which drives gst-launch-1.0 for capture and fixes the black-screen + pts-timing issues on that path (DMA-BUF import + 4:2:0 chroma). doubletake builds CGO-free and only needs the gst-launch-1.0 CLI plus plugins at runtime:

Potential blocker

Status

Slices: discovery, cast, screen-mirror, Control Center widget/service, auto-reconnect. AirPlay 2 mirroring has been verified against a real non-Apple AirPlay 2 receiver; Chromecast paths are built but not yet verified against real Cast hardware.

Screenshot from 2026-06-24 11-42-07

domenkozar and others added 3 commits June 24, 2026 19:08
New cast manager in the core daemon: mDNS discovery of both Google Cast
(_googlecast._tcp) and AirPlay (_airplay._tcp) devices, connect, live
playback status, media casting with transport controls, and screen
mirroring. Exposed over JSON-RPC and wired into the server/router.

Discovery prefers avahi via D-Bus when it is running (no parallel mDNS
stack, so it avoids UDP 5353 contention) and otherwise falls back to a
self healing zeroconf/go-chromecast browser that re-browses periodically.
AirPlay devices are keyed by their stable mDNS instance name rather than
the flaky deviceid TXT. A preferred device auto connects when discovered.

Screen capture and encode run in dms-cast-helper, a cgo gated go-gst
program (VA-API DMA-BUF import, I420 chroma, PTS restamp) kept separate
so the core stays CGO free. Chromecast mirrors via HLS served from core;
AirPlay mirrors via the external doubletake process.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ChromecastService.qml subscribes to the core cast manager and exposes
discovery, connect/disconnect, transport controls, screen mirroring and
preferred device, with the mDNS browse refcounted to the detail panel.

A new Control Center widget (ChromecastWidget) and detail panel
(ChromecastDetailContent) list both Chromecast and AirPlay devices,
pin the connected device to the top of the list (no duplicate card),
and offer stop mirroring plus an auto connect star per device.
Registered in the widget model and Control Center components, and added
to the default widget set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Covers Chromecast and AirPlay discovery (avahi preferred, with a self
healing zeroconf fallback), building dms-cast-helper, the external
doubletake dependency for AirPlay, the firewall port range, and the
mDNS port 5353 contention gotcha (notably Chrome).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Purian23 Purian23 requested a review from bbedward June 25, 2026 01:16
@bbedward

Copy link
Copy Markdown
Collaborator

CGO is a hard no from me, along with the GPL3 lib which isn't a potential blocker it is a blocker because we need to be able to distribute DMS with vendored modules, which makes the license incompatibility a blocker (for example, Fedora/Redhat wouldnt be able to package dms anymore under the current license).

The feature is good and actually very useful (I appreciate the contribution and thoughtfulness of it), but we'd have to find another way to implement it. Anything that depends on C would need to be a binary entirely external from dms or built into quickshell itself basically.

I would be more open to this one being a plugin, unless we could workaround the CGO requirements (by either not needing gstreamer, building it into quickshell, or referencing an external binary/dependency that wasn't vendored into dms at all)

@domenkozar

Copy link
Copy Markdown
Contributor Author

CGO is a hard no from me, along with the GPL3 lib which isn't a potential blocker it is a blocker because we need to be able to distribute DMS with vendored modules, which makes the license incompatibility a blocker (for example, Fedora/Redhat wouldnt be able to package dms anymore under the current license).

I'm talking to upstream to potentially relicense so that we can ship it. Fingers crossed.

Anything that depends on C would need to be a binary entirely external from dms or built into quickshell itself basically.

Maybe I should just apply fixes upstream to use gstreamer cli like it used to be in omarroth/doubletake#9 and we're good to include it by default.

@domenkozar

Copy link
Copy Markdown
Contributor Author

I would be more open to this one being a plugin, unless we could workaround the CGO requirements (by either not needing gstreamer, building it into quickshell, or referencing an external binary/dependency that wasn't vendored into dms at all)

I've reverted the CGO change in upstream PR, still discussing licensing options.

The doubletake fork was reworked to drop the go-gst (CGO) capture path and
drive gst-launch-1.0 instead, fixing the black-screen + pts-timing issues on
that path. Update casting docs (build no longer needs CGO or GStreamer dev
packages) and the airplay_mirror comment to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Spoch-dev

This comment was marked as spam.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants